package org.noote.libs.tcpip;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.concurrent.LinkedBlockingQueue;

import android.util.Log;

	public class IPClient_ConnectedThread extends Thread {
		private static final String TAG = "IPClient.ConnectedThread";

		private InputStream mmInStream = null;
		private OutputStream mmOutStream = null;
		private Socket mSocket = null;
		private PrintWriter out = null;
		
		private boolean _bIsConnected = false;
		private boolean _bIsDebug = false;
		
		private IPEvent_Client _events = null;
		
		private final LinkedBlockingQueue<String> mQueue = new LinkedBlockingQueue<String>();

		public IPClient_ConnectedThread(Socket socket, IPEvent_Client events) {
			this.mSocket = socket;
			this._events = events;
			InputStream tmpIn = null;
			OutputStream tmpOut = null;
			
			_events.setThread(this);

			// Get the input and output streams, using temp objects because
			// member streams are final
			try {
				tmpIn = socket.getInputStream();
				tmpOut = socket.getOutputStream();
			} catch (IOException e) {
				_events.onError("ConnectedThread() : cannot get I/O handlers, catch IOException "+e.getMessage());
				return;
			}
			if(tmpIn == null || tmpOut==null)
			{
				_events.onError("ConnectedThread() : cannot get I/O handlers");
				return;
			}

			mmInStream = tmpIn;
			mmOutStream = tmpOut;
			try {
				mmOutStream.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			out = new PrintWriter(new BufferedWriter(
					new OutputStreamWriter(mmOutStream), 1024*32), true);
		}

		public boolean isConnected(){return _bIsConnected;}
		
		@Override
		public void run() {
			if(mmInStream == null || mmOutStream == null)
				return;
			
			_bIsConnected = true;
			try {
				mmOutStream.flush();
			} catch (IOException e) {
			}
			_events.onConnected();
	    	
            BufferedReader in = new BufferedReader(new InputStreamReader(mmInStream), 1024*32);
	    	String line = null;
            try {
				while ((line = in.readLine()) != null) {
					if(_bIsDebug)
						Log.d(TAG, "Receive line : " + line);
					// have we a command or a result ?
					if(line.contains("#") && line.contains("$"))
					{
						int offset = 0;
						while(true)
						{
							int idx_start = line.indexOf("#", offset);
							if(idx_start == -1) break;
							int idx_end = line.indexOf("$", idx_start);
							if(idx_end == -1) break;
							offset = idx_end+1;
							
							_events.onCmd(line.substring(idx_start+1, idx_end));
						}
					}
					else // else it's only text...
					{
						_events.onText(line);						
					}
				}
			} catch (IOException e) {
				_events.onError("readLine() : I/O Exception " + e.toString());			
			}
			close();
			_bIsConnected = false;
	    }

		/* Call this from the main Activity to send data to the remote device */
		public boolean sendQueued(String sMessage) {
			
			try {
				mQueue.put(sMessage);
				
				while(!mQueue.isEmpty())
				{
					String sMsg = mQueue.take();
					
					out.println(sMsg);
					
					if(_bIsDebug)
						Log.d(TAG, "Sended message : " + sMessage);
				}
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
				return false;
			}
			return true;
		}
		public boolean sendMessage(String sMessage) {
			return sendQueued(sMessage);
		}
		public boolean sendCommand(String sCmd, String sOp) {
			return sendMessage("#"+sCmd.toLowerCase()+":"+sOp+"$");
		}

		/* Call this from the main Activity to shutdown the connection */
		public void close() {
			try {
				mSocket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
            _events.onDisconnected();
		}
	}
